package model;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.HashSet;
import java.util.Set;

import javax.xml.bind.annotation.XmlTransient;

import util.CollectionChangeEvent;
import util.CollectionChangeListener;
import util.CollectionChangeSupport;

import model.menu.AppHomeModel;
import model.menu.JoinProjectMenuModel;
import model.menu.ManageProjectsMenuModel;
import model.menu.NewProjectMenuModel;

public class ApplicationModel {
	public enum Property {
		PROJECTS, CURRENT_PROJECT
	}

	@XmlTransient
	private CollectionChangeSupport<Project> projectCollectionChangeSupport = new CollectionChangeSupport<Project>(
			this);
	@XmlTransient
	private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
			this);

	private AppHomeModel appHomeModel;
	private NewProjectMenuModel newProjectMenuModel;
	private ManageProjectsMenuModel manageProjectsMenuModel;
	private JoinProjectMenuModel joinProjectMenuModel;

	private Project currentProject;
	private Set<Project> projects;

	public ApplicationModel(Set<Project> projects) {
		super();
		this.projects = projects;
		this.appHomeModel = new AppHomeModel(this.projects);
		this.newProjectMenuModel = new NewProjectMenuModel(this.projects);
		this.manageProjectsMenuModel = new ManageProjectsMenuModel(
				this.projects);
		this.joinProjectMenuModel = new JoinProjectMenuModel(this.projects);
	}

	public Set<Project> getProjects() {
		return projects;
	}

	public void setProjects(Set<Project> projects) {
		Set<Project> oldProjects = new HashSet<Project>(this.projects);
		this.projects = projects;
		propertyChangeSupport.firePropertyChange(Property.PROJECTS.name(),
				oldProjects, this.projects);
	}

	public void addProject(Project project) {
		this.projects.add(project);
		this.projectCollectionChangeSupport.fireCollectionChanged(project,
				CollectionChangeEvent.Type.ADD);
	}

	public void removeProject(Project project) {
		if (projects.contains(project)) {
			this.projects.remove(project);
			this.projectCollectionChangeSupport.fireCollectionChanged(project,
					CollectionChangeEvent.Type.REMOVE);
		}
	}

	

	public void addPropertyChangeListener(Property property,
			PropertyChangeListener listener) {
		this.propertyChangeSupport.addPropertyChangeListener(property.name(),
				listener);
	}

	public void removePropertyChangeListener(Property property,
			PropertyChangeListener listener) {
		this.propertyChangeSupport.removePropertyChangeListener(
				property.name(), listener);
	}

	public AppHomeModel getAppHomeModel() {
		return appHomeModel;
	}

	public NewProjectMenuModel getNewProjectMenuModel() {
		return newProjectMenuModel;
	}

	public ManageProjectsMenuModel getManageProjectsMenuModel() {
		return manageProjectsMenuModel;
	}

	public JoinProjectMenuModel getJoinProjectMenuModel() {
		return joinProjectMenuModel;
	}

	public Project getCurrentProject() {
		return currentProject;
	}

	public void setCurrentProject(Project currentProject) {
		if (currentProject == null || currentProject != this.currentProject) {
			Project oldCurrentProject = this.currentProject;
			this.currentProject = currentProject;
			propertyChangeSupport.firePropertyChange(
					Property.CURRENT_PROJECT.name(), oldCurrentProject,
					this.currentProject);
		}
	}

	public void addCollectionChangeListener(
			CollectionChangeListener<Project> listener) {
		this.projectCollectionChangeSupport.addCollectionListener(listener);
	}

	public void removeCollectionChangeListener(
			CollectionChangeListener<Project> listener) {
		this.projectCollectionChangeSupport.removeCollectionListener(listener);
	}
}
